from flask import jsonify, request
from app.api.v1 import bp
from app.models.marine_data import MarineData
from datetime import datetime, timedelta
from sqlalchemy import func
import numpy as np
from app import db
from app.models.sea_temperature import SeaTemperature
import pandas as pd
from prophet import Prophet
import os

@bp.route('/marine-data/<int:area_id>', methods=['GET'])
def get_marine_data(area_id):
    """获取海域数据，包括温度、气压和浪涌"""
    # 获取当前时间
    now = datetime.now()
    # 检查sea_temperatures表第一行measurement_date是否为今天，如果不是则重置所有相关时间
    first_sea_temp = db.session.query(SeaTemperature).order_by(SeaTemperature.id).first()
    if first_sea_temp:
        first_date = first_sea_temp.measurement_date
        today = now.date()
        if first_date != today:
            # 需要重置marine_data表所有历史和预测数据的measurement_time
            # 历史数据（is_predicted=False）
            history_data = db.session.query(MarineData).filter(MarineData.is_predicted==False).order_by(MarineData.id).all()
            for i, d in enumerate(history_data):
                d.measurement_time = now - timedelta(hours=72-24*i)
            # 预测数据（is_predicted=True）
            prediction_data = db.session.query(MarineData).filter(MarineData.is_predicted==True).order_by(MarineData.id).all()
            for i, d in enumerate(prediction_data):
                d.measurement_time = now + timedelta(hours=24*(i+1))
            # 重置sea_temperatures表的measurement_date为今天
            sea_temps = db.session.query(SeaTemperature).all()
            for st in sea_temps:
                st.measurement_date = now.date()
            db.session.commit()
    
    # 获取72小时前的时间点
    history_start = now - timedelta(hours=72)
    
    # 查询历史数据
    temperature_data = MarineData.query.filter(
        MarineData.marine_area_id == area_id,
        MarineData.data_type == 'temperature',
        MarineData.measurement_time >= history_start,
        MarineData.is_predicted == False
    ).all()
    
    pressure_data = MarineData.query.filter(
        MarineData.marine_area_id == area_id,
        MarineData.data_type == 'pressure',
        MarineData.measurement_time >= history_start,
        MarineData.is_predicted == False
    ).all()
    
    wave_data = MarineData.query.filter(
        MarineData.marine_area_id == area_id,
        MarineData.data_type == 'wave',
        MarineData.measurement_time >= history_start,
        MarineData.is_predicted == False
    ).all()
    
    # 获取预测数据
    future_end = now + timedelta(hours=72)
    temperature_prediction = MarineData.query.filter(
        MarineData.marine_area_id == area_id,
        MarineData.data_type == 'temperature',
        MarineData.measurement_time <= future_end,
        MarineData.is_predicted == True
    ).all()
    
    pressure_prediction = MarineData.query.filter(
        MarineData.marine_area_id == area_id,
        MarineData.data_type == 'pressure',
        MarineData.measurement_time <= future_end,
        MarineData.is_predicted == True
    ).all()
    
    # 计算浪涌周期
    wave_peaks = [float(d.value) for d in wave_data if float(d.value) > 0]
    avg_period = len(wave_peaks) / 24 if wave_peaks else 0  # 平均每天的峰值次数
    next_threshold = calculate_next_threshold(wave_peaks) if wave_peaks else None
    
    return jsonify({
        'temperature': {
            'history': [{
                'time': d.measurement_time.strftime('%Y-%m-%d %H:%M:%S'),
                'value': float(d.value),
                'lat': float(d.latitude),
                'lng': float(d.longitude)
            } for d in temperature_data],
            'prediction': [{
                'time': d.measurement_time.strftime('%Y-%m-%d %H:%M:%S'),
                'value': float(d.value),
                'lat': float(d.latitude),
                'lng': float(d.longitude)
            } for d in temperature_prediction]
        },
        'pressure': {
            'history': [{
                'time': d.measurement_time.strftime('%Y-%m-%d %H:%M:%S'),
                'value': float(d.value)
            } for d in pressure_data],
            'prediction': [{
                'time': d.measurement_time.strftime('%Y-%m-%d %H:%M:%S'),
                'value': float(d.value)
            } for d in pressure_prediction]
        },
        'wave': {
            'data': [{
                'time': d.measurement_time.strftime('%Y-%m-%d %H:%M:%S'),
                'value': float(d.value)
            } for d in wave_data],
            'avg_period': avg_period,
            'next_threshold': next_threshold
        }
    })

def calculate_next_threshold(wave_peaks):
    """预测下一个浪涌阈值"""
    # 这里可以实现更复杂的预测算法
    if not wave_peaks:
        return None
    return {
        'value': np.mean(wave_peaks) + np.std(wave_peaks),
        'days': 3  # 示例：预测3天后达到阈值
    }

@bp.route('/marine-forecast/<int:id>', methods=['GET'])
def marine_forecast(id):
    """
    根据id返回不同csv的气压、温度预测、浪高峰值天数和平均浪周期
    id=3:XMD2023.csv, id=4:LYG2023.csv, id=5:XMN2023.csv
    """
    file_map = {
        3: 'XMD2023.csv',
        4: 'LYG2023.csv',
        5: 'XMN2023.csv'
    }
    file_path = file_map.get(id)
    if not file_path:
        return jsonify({'error': '无效的id'}), 400

    try:
        file_name = list(file_path.split('.')[0][-1:-5:-1])
        file_name.reverse()
        year = ('').join(file_name)
        # 跨平台更安全：
        csv_path = os.path.join('data', file_path)
        df = pd.read_csv(csv_path)
        if df.empty:
            return jsonify({'error': '文件不存在或文件为空'}), 400
        
        df['ds'] = pd.to_datetime(year + df['Date'].astype(str) + ' ' + df['Time'].astype(str) + ':00:00', format='%Y%j %H:%M:%S')
        # 气压
        pressure_df = df[['ds', 'Air_Pressure']].rename(columns={'Air_Pressure': 'y'})
        # 海温
        temperature_df = df[['ds', 'Sea_Temperature']].rename(columns={'Sea_Temperature': 'y'})
        # Prophet模型
        pressure_model = Prophet()
        pressure_model.fit(pressure_df)
        temperature_model = Prophet()
        temperature_model.fit(temperature_df)
        future_dates = pressure_model.make_future_dataframe(periods=3, freq='h')
        pressure_forecast = pressure_model.predict(future_dates)
        pressure_forecast_last_three = pressure_forecast[['ds', 'yhat']].tail(3).rename(columns={'yhat': 'Air_Pressure_Prediction'}).round(2)
        temperature_forecast = temperature_model.predict(future_dates)
        temperature_forecast_last_three = temperature_forecast[['ds', 'yhat']].tail(3).rename(columns={'yhat': 'Sea_Temperature_Prediction'}).round(2)
        combined_forecast = pd.merge(pressure_forecast_last_three, temperature_forecast_last_three, on='ds')
        # 修改ds为指定日期
        combined_forecast['ds'] = [f'2025-05-{16+i}' for i in range(len(combined_forecast))]
        # 浪高峰值
        historical_max_index = df['Wind_Wave_Height'].idxmax()
        remaining_data = df.loc[historical_max_index + 1:, 'Wind_Wave_Height']
        if remaining_data.empty:
            next_peak_days = None
        else:
            next_max_index = remaining_data.idxmax()
            next_peak_hours = (next_max_index - historical_max_index)
            next_peak_days = round(next_peak_hours / 24, 3)
        average_wave_period = round(df['Wind_Wave_Period'].mean(), 2)
        return jsonify({
            'forecast': combined_forecast.to_dict(orient='records'),
            'next_peak_days': next_peak_days,
            'average_wave_period': average_wave_period
        })
    except Exception as e:
        return jsonify({'error': str(e)}), 500 
    
# 获取海域数据
@bp.route('/marine-data/<int:id>/station', methods=['GET'])
def get_station_data(id):
    """
    根据id读取对应csv文件，返回Date从01到15每天12点的数据
    id=3:XMD2023.csv, id=4:LYG2023.csv, id=5:XMN2023.csv
    """
    file_map = {
        3: 'XMD2023.csv',
        4: 'LYG2023.csv',
        5: 'XMN2023.csv'
    }
    file_path = file_map.get(id)
    if not file_path:
        return jsonify({'error': '无效的id'}), 400
    try:
        # 假设csv文件在项目根目录下的data文件夹
        csv_path = os.path.join('data', file_path)
        df = pd.read_csv(csv_path)
        if df.empty:
            return jsonify({'error': '文件不存在或文件为空'}), 400
        # 只保留Date为01到15且Time为12的数据
        df['Date'] = df['Date'].astype(str).str.zfill(2)
        filtered = df[(df['Date'].isin([f'{i:02d}' for i in range(1, 16)])) & (df['Time'].astype(str) == '12')]
        # 只保留需要的字段
        filtered = filtered[['Air_Pressure', 'Air_Temperature', 'Date', 'Sea_Temperature', 'Wind_Wave_Height']]
        # 保留两位小数
        filtered['Air_Pressure'] = filtered['Air_Pressure'].round(2)
        filtered['Air_Temperature'] = filtered['Air_Temperature'].round(2)
        filtered['Sea_Temperature'] = filtered['Sea_Temperature'].round(2)
        filtered['Wind_Wave_Height'] = filtered['Wind_Wave_Height'].round(2)
        return jsonify({
            'data': list(filtered.to_dict(orient='records')),
        })
    except Exception as e:
        return jsonify({'error': str(e)}), 500